using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Text.RegularExpressions;
using System.IO;
using PSE.ProcessManager.Entity;
using PSE.ProcessManager.ServiceManager;
using PSE.Framework.Configuration;
using PSE.Framework.ErrorLogging;
using System.Linq;

namespace PSE.ProcessManager.ServiceManagerApplication
{
    public static class Business
    {
        private const char ServerConfigSeparator = '|';
        private const string Localhost = "localhost";
        private static Regex ServerNameRegEx = new Regex("^([^,~:|!@#$%\\^&'.\\(\\){}_]){1,24}$");
        private static Regex PackageNameRegEx = new Regex("^([^,~:|!@#$%\\^&'\\(\\){}]){1,24}$");

        #region Server Methods

        public static List<string> GetServersFromConfigurationFile()
        {
            List<string> servers = new List<string>();

            // Adiciona o localhost.
            servers.Add(Localhost);

            string serverList = Properties.Settings.Default.Servers;

            if (!string.IsNullOrEmpty(serverList))
            {
                string[] tempServers = serverList.Split(ServerConfigSeparator);
                for (int i = 0; i < tempServers.Length; i++)
                {
                    servers.Add(tempServers[i].ToUpper());
                }
            }

            return servers;
        }

        public static bool ValidateServerName(string serverName)
        {
            return ServerNameRegEx.IsMatch(serverName);
        }

        public static bool ValidatePackageName(string packageName)
        {
            return PackageNameRegEx.IsMatch(packageName);
        }

        public static bool IsServerStarted(string serverName)
        {
            ServiceManager.ServiceManager serviceManager = new ServiceManager.ServiceManager(serverName);

            return serviceManager.GetStatus() == System.ServiceProcess.ServiceControllerStatus.Running;
        }

        public static void AddServer(string serverName)
        {
            // Read the added servers from configuration file.
            string serverList = Properties.Settings.Default.Servers;

            if (!String.IsNullOrEmpty(serverList))
                serverList += ServerConfigSeparator.ToString();

            serverList += serverName.ToUpper();

            Properties.Settings settings = Properties.Settings.Default;
            settings.Servers = serverList;
            settings.Save();
        }

        public static void RemoveServer(string serverName)
        {
            char[] separators = { ServerConfigSeparator };

            // Read the added servers from configuration file.
            string serverList = Properties.Settings.Default.Servers;

            serverList = serverList.Replace(serverName, "");
            serverList = serverList.Replace(ServerConfigSeparator.ToString() + ServerConfigSeparator.ToString(), ServerConfigSeparator.ToString());
            serverList = serverList.TrimStart(separators);
            serverList = serverList.TrimEnd(separators);

            Properties.Settings settings = Properties.Settings.Default;
            settings.Servers = serverList;
            settings.Save();

        }

        #endregion

        #region Product Methods

        public static List<string> ListProducts(string serverName)
        {
            try
            {
                List<String> products = new List<string>();

                ServiceManager.ServiceManager serviceManager = new ServiceManager.ServiceManager(serverName);

                if (serviceManager.GetStatus() == System.ServiceProcess.ServiceControllerStatus.Running)
                {
                    foreach (string prod in serviceManager.ListProducts())
                    {
                        products.Add(prod);
                    }
                }

                return products;
            }
            catch (Exception ex)
            {
                ErrorLogger.WriteLog(LogType.Error, ex);
                throw;
            }
        }

        #endregion

        #region Instance Methods

        public static List<Instance> ListInstances(string serverName, string productName)
        {
            try
            {
                List<Instance> instances = new List<Instance>();

                ServiceManager.ServiceManager serviceManager = new ServiceManager.ServiceManager(SystemComponents.GetSystem(productName), serverName);

                if (serviceManager.GetStatus() == System.ServiceProcess.ServiceControllerStatus.Running)
                {
                    foreach (InstanceEntity inst in serviceManager.ListInstances(productName))
                    {
                        Instance instance = new Instance();
                        instance.ProcessId = inst.ProcessId;
                        instance.ProductName = productName;
                        instance.InstanceName = inst.Name;
                        instances.Add(instance);
                    }
                }

                return instances;
            }
            catch (Exception ex)
            {
                ErrorLogger.WriteLog(LogType.Error, ex);
                throw;
            }
        }

        public static bool StartInstance(string serverName, string productName, string instanceName)
        {
            try
            {
                ServiceManager.ServiceManager serviceManager = new ServiceManager.ServiceManager(SystemComponents.GetSystem(productName), serverName);

                return serviceManager.GetStatus() == System.ServiceProcess.ServiceControllerStatus.Running &&
                       serviceManager.StartInstance(productName, instanceName);
            }
            catch (Exception ex)
            {
                ErrorLogger.WriteLog(LogType.Error, ex);
                throw;
            }
        }

        public static bool StopInstance(string serverName, string productName, string instanceName)
        {
            try
            {
                ServiceManager.ServiceManager serviceManager = new ServiceManager.ServiceManager(SystemComponents.GetSystem(productName), serverName);

                return serviceManager.GetStatus() == System.ServiceProcess.ServiceControllerStatus.Running &&
                       serviceManager.StopInstance(productName, instanceName);
            }
            catch (Exception ex)
            {
                ErrorLogger.WriteLog(LogType.Error, ex);
                throw;
            }
        }

        public static bool RestartInstance(string serverName, string productName, string instanceName)
        {
            try
            {
                ServiceManager.ServiceManager serviceManager = new ServiceManager.ServiceManager(SystemComponents.GetSystem(productName), serverName);

                return serviceManager.GetStatus() == System.ServiceProcess.ServiceControllerStatus.Running &&
                       serviceManager.RestartInstance(productName, instanceName);
            }
            catch (Exception ex)
            {
                ErrorLogger.WriteLog(LogType.Error, ex);
                throw;
            }
        }

        public static bool IsInstanceStarted(string serverName, string productName, string instanceName)
        {
            try
            {
                ServiceManager.ServiceManager serviceManager = new ServiceManager.ServiceManager(SystemComponents.GetSystem(productName), serverName);

                return serviceManager.GetStatus() == System.ServiceProcess.ServiceControllerStatus.Running &&
                       serviceManager.IsInstanceStarted(productName, instanceName);
            }
            catch (Exception ex)
            {
                ErrorLogger.WriteLog(LogType.Error, ex);
                throw;
            }
        }

        #endregion

        #region Process Methods

        public static List<ProcessEntity> ListProcesses(string serverName, string productName, string instanceName)
        {
            try
            {
                ServiceManager.ServiceManager serviceManager = new ServiceManager.ServiceManager(SystemComponents.GetSystem(productName), serverName);

                List<ProcessEntity> processes = new List<ProcessEntity>();

                if (serviceManager.GetStatus() == System.ServiceProcess.ServiceControllerStatus.Running)
                {
                    processes = serviceManager.ListProcesses(productName, instanceName);
                }

                return processes;
            }
            catch (Exception ex)
            {
                ErrorLogger.WriteLog(LogType.Error, ex);
                throw;
            }
        }

        public static bool IsProcessStarted(string serverName, string productName, string instanceName, int processId)
        {
            try
            {
                ServiceManager.ServiceManager serviceManager = new ServiceManager.ServiceManager(SystemComponents.GetSystem(productName), serverName);

                return serviceManager.GetStatus() == System.ServiceProcess.ServiceControllerStatus.Running &&
                       serviceManager.IsProcessStarted(productName, instanceName, processId);
            }
            catch (Exception ex)
            {
                ErrorLogger.WriteLog(LogType.Error, ex);
                throw;
            }
        }

        public static bool StartProcess(string serverName, string productName, string instanceName, int processId)
        {
            try
            {
                ServiceManager.ServiceManager serviceManager = new ServiceManager.ServiceManager(SystemComponents.GetSystem(productName), serverName);

                return serviceManager.GetStatus() == System.ServiceProcess.ServiceControllerStatus.Running &&
                       serviceManager.StartProcess(productName, instanceName, processId);
            }
            catch (Exception ex)
            {
                ErrorLogger.WriteLog(LogType.Error, ex);
                throw;
            }
        }

        public static bool StopProcess(string serverName, string productName, string instanceName, int processId)
        {
            try
            {
                ServiceManager.ServiceManager serviceManager = new ServiceManager.ServiceManager(SystemComponents.GetSystem(productName), serverName);

                return serviceManager.GetStatus() == System.ServiceProcess.ServiceControllerStatus.Running &&
                       serviceManager.StopProcess(productName, instanceName, processId);
            }
            catch (Exception ex)
            {
                ErrorLogger.WriteLog(LogType.Error, ex);
                throw;
            }
        }

        #endregion

        private static List<InteligenceModuleEntity> _inteligenceModules = null;

        public static InteligenceModuleEntity GetInteligenceModule(string serverName, int inteligenceModuleId)
        {
            try
            {
                if (_inteligenceModules == null)
                {
                    ServiceManager.ServiceManager serviceManager = new ServiceManager.ServiceManager(serverName);

                    _inteligenceModules = new List<InteligenceModuleEntity>();

                    if (serviceManager.GetStatus() == System.ServiceProcess.ServiceControllerStatus.Running)
                    {
                        _inteligenceModules = serviceManager.ListInteligenceModules();
                    }
                }

                return _inteligenceModules.First(i => i.Id.Value == inteligenceModuleId);
            }
            catch (Exception ex)
            {
                ErrorLogger.WriteLog(LogType.Error, ex);
                throw;
            }
        }
    }
}
